package cn.dengta.webapp.trade.service;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;

import cn.dengta.common.util.SpringUtil;
import cn.dengta.webapp.base.service.BaseServiceImpl;
import cn.dengta.webapp.trade.dao.AreaDao;
import cn.dengta.webapp.trade.entity.Area;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import me.codeplayer.util.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import static cn.dengta.webapp.base.entity.BaseEntity.ID;
import static cn.dengta.webapp.trade.entity.Area.*;

/**
 * 地区信息表 服务实现类
 *
 * @author HCG
 * @since 2023-03-15
 */
@Service
public class AreaService extends BaseServiceImpl<Area, AreaDao, Long> implements InitializingBean {

	/** < Area.id, < fullName, name > > */
	static LazyCacheLoader<Map<Long, Area.CacheNode>> cache;
	static LazyCacheLoader<List<Area>> allCache;

	public LazyCacheLoader<Map<String, Area>> areaMapCache = new TimeBasedCacheLoader<>(EasyDate.MILLIS_OF_DAY, this::findMap);

	private Map<String, Area> findMap() {
		List<Area> areas = areaCache.get();
		return CollectionUtil.toHashMap(areas, Area::getName);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		cache = new TimeBasedCacheLoader<>(EasyDate.MILLIS_OF_DAY, () -> Collections.unmodifiableMap(CollectionUtil.toHashMap(findAllFullNames(), Area::getId, CacheNode::new)));
		allCache = new TimeBasedCacheLoader<>(EasyDate.MILLIS_OF_DAY, this::findAll);
	}

	public Map<Long, Area> loadMap() {
		return Collections.unmodifiableMap(CollectionUtil.toHashMap(allCache.get(), Area::getId));
	}

	public static String getName(Long id) {
		return getName(id, false);
	}

	static String getName(Long id, boolean fullOrShort) {
		final Map<Long, Area.CacheNode> map = cache.get();
		final Area.CacheNode pair = map.get(id);
		return pair == null ? null : fullOrShort ? pair.getFullName() : pair.getName();
	}

	public static String getFullName(Long id) {
		return getName(id, true);
	}

	/** < Area.id, < fullName, name > > */
	public static Map<Long, Area.CacheNode> allCache() {
		return cache.get();
	}

	List<Area> findAllFullNames() {
		final QueryWrapper<Area> wrapper = new QueryWrapper<Area>()
				.select(ID, FULL_NAME, NAME, LOCATION);
		return selectList(wrapper);
	}

	public LazyCacheLoader<List<Area>> areaCache = new TimeBasedCacheLoader<>(EasyDate.MILLIS_OF_DAY, this::findAll);

	public List<Area> calcAreaListTree(@Nonnull String level) {
		final Integer lv = X.expectNotNull(Area.mapLevel(level), Area.DISTRICT_LEVEL);
		if (areaCache == null) {
			areaCache = new TimeBasedCacheLoader<>(EasyDate.MILLIS_OF_DAY, this::findAll);
		}
		final List<Area> list = areaCache.get().stream().filter(t -> t.getLevel() <= lv).collect(Collectors.toList());
		return Area.PROVINCE_LEVEL.equals(lv) ? list : buildTree(list);
	}

	private List<Area> buildTree(List<Area> areas) {
		Map<Long, List<Area>> areaMap = areas.stream().collect(Collectors.groupingBy(Area::getParentId));
		for (Area area : areas) {
			area.setChildren(areaMap.get(area.getId()));
		}
		return areas.stream().filter(Area::isProvince).collect(Collectors.toList());
	}

	public static Integer name2Id(String name) {
		if (StringUtil.isEmpty(name)) {
			return 0;
		}
		AreaService areaService = SpringUtil.getBean(AreaService.class);
		if (areaService == null) {
			return 0;
		}
		return areaService.doName2Id(name);
	}

	public Integer doName2Id(String name) {
		if (StringUtil.isEmpty(name)) {
			return 0;
		}

		Map<String, Area> areaMap = areaMapCache.get();

		Area area = areaMap.get(name);
		if (area == null) {
			area = areaMap.get(name + "州");
		}
		if (area == null) {
			return 0;
		}
		return area.getId().intValue();
	}

}
